﻿using AutoMapper;
using B.S.BasicData.Api.Read.Extensions;
using B.S.BasicData.Api.Write.Application.Command.GridPerson;

using B.S.BasicData.Domain.Entities;
using B.S.BasicData.ErrorCode;
using B.S.BasicData.Infrastructure.Implement;
using B.S.BasicData.Infrastructure.Interface;
using MD5Hash;
using MediatR;
using System.Transactions;
using Yitter.IdGenerator;

namespace B.S.BasicData.Api.Write.Application.Handler.GridPerson
{

    /// <summary>
    /// 添加网格人员的处理类
    /// </summary>
    public class CreateGridPersonHandler : IRequestHandler<CreateGridPersonCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<AccountModel> accountRepo;
        private readonly IBaseRepository<AccountRoleModel> accountRoleRepo;
        private readonly IBaseRepository<LogModel> logRepo;
        private readonly IMapper mapper;
        private readonly ILogger<CreateGridPersonHandler> logger;

        //需要哪些仓储和组件?
        /// <summary>
        /// 
        /// </summary>
        /// <param name="accountRepo">账号仓储</param>
        /// <param name="accountRoleRepo">账号角色仓储</param>
        /// <param name="logRepo">日志仓储</param>
        /// <param name="mapper">automaopper</param>
        /// <param name="logger">Nlog日志组件</param>
        public CreateGridPersonHandler(IBaseRepository<AccountModel> accountRepo,IBaseRepository<AccountRoleModel> accountRoleRepo,IBaseRepository<LogModel> logRepo,IMapper mapper,ILogger<CreateGridPersonHandler> logger)
        {
            this.accountRepo = accountRepo;
            this.accountRoleRepo = accountRoleRepo;
            this.logRepo = logRepo;
            this.mapper = mapper;
            this.logger = logger;
        }

        /// <summary>
        /// 添加网格人员的处理方法
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> Handle(CreateGridPersonCommand request, CancellationToken cancellationToken)
        {
            ApiResult<int> res = new ApiResult<int>();

            //构建账号model,使用automapper更方便
            var accountModel = mapper.Map<AccountModel>(request);
            accountModel.Id = YitIdHelper.NextId();//崭新的id
            accountModel.Salt = this.GenerateSalt();//给盐赋值
            accountModel.Pwd = request.CardId.Substring(request.CardId.Length - 6).GetMD5WithSalt(accountModel.Salt);



            //构建账号角色model

            var accountRoleModel = new AccountRoleModel()
            {
                Id = YitIdHelper.NextId(),//崭新的id
                AccountId = accountModel.Id,
                RoleId = request.RoleId,
            };
            //构建日志model
            var logModel = new LogModel() {
                Id = YitIdHelper.NextId(),//崭新的id
                LogDes = $"正在添加新的网格人员:{accountModel.RealName}",
                Creator = request.Creator,
                CreateTime = DateTime.Now
            };

            int r1 = 0;
            int r2 = 0;
            //使用using 来开启分布式事务
            using (TransactionScope tran =new TransactionScope( TransactionScopeAsyncFlowOption.Enabled))
            {
                try
                {
                    r1 = await accountRepo.CreateAsync(accountModel);//把构建好的 账号 实体对象保存到数据库 (2.原子性)
                    r2 = await accountRoleRepo.CreateAsync(accountRoleModel);//把构建好的 账号角色 实体对象保存到数据库
                    tran.Complete();//提交事务(1.一致性)
                }
                catch (Exception e)
                {
                    logger.LogError("事务中发生异常:"+e.Message); 
                }
            }//(3.隔离性)  4.持久化

            //日志
            logRepo.CreateAsync(logModel); //不需要等待,提升性能

            if (r1 > 0 && r2 > 0)
            {

                res.Code = ApiEnum.Success;
                res.Data = r1;
                res.Msg = "添加网格人员成功.";
            }
            else {
                res.Code = ApiEnum.Failed;
                res.Data = 0;
                res.Msg = "添加网格人员失败.";
            }
            return res;
        } 
    }
}
